package com.mk.datapower.aspect;

import com.alibaba.fastjson.JSON;
import com.mk.datapower.annotation.APIDataPower;
import com.mk.datapower.bean.bo.MemberDetailDataApi;
import com.mk.datapower.bean.bo.MemberInfoDataApi;
import com.mk.datapower.enums.ApiDataPowerMethodEnum;
import com.mk.datapower.enums.ApiDataPowerServerEnum;
import com.mk.datapower.holder.RequestHolder;
import com.mk.datapower.service.DataPowerService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author peisong.chen
 * @date 2019/7/29
 */
@Aspect
@Component
public class DataPowerAspect {
    private static final Logger logger = LoggerFactory.getLogger(DataPowerAspect.class);
    @Autowired
    private DataPowerService dataPowerService;

    /**
     * 切入点，加此注解的方法，都会执行该类中的代码
     */
    @Pointcut("@annotation(com.mk.datapower.annotation.APIDataPower)")
    public void execute() {
    }

    @Around("execute()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        Method method = signature.getMethod();

        APIDataPower annotation = method.getAnnotation(APIDataPower.class);
        ApiDataPowerServerEnum source = annotation.source();
        String tableName = annotation.tableName().name();
        String methodTypeName = annotation.method().name();
        // 从请求头的Header中获取数据
        HttpServletRequest request = RequestHolder.getRequest();
        String orgId = request.getHeader("orgId");
        String userId = request.getHeader("userId");
        logger.info("DataPowerAspect ->>> source:{},operateTableName:{},orgId:{},userId:{}", source, tableName, orgId, userId);

        Object proceed = proceedingJoinPoint.proceed();
        Class proceedClass = proceed.getClass();
        logger.info("DataPowerAspect ->>> proceedClass ：{}", proceedClass);

        /**
         * 该切面过滤CRM_SERVER的接口,如果有多个服务模块过滤可以用if判断，此处只有一个
         * 正常情况应该是：将此类写在公共模块中，其他微服务模块引用此模块代码，将此切面注入到具体的方法上
         */
        if (source.name().equals(ApiDataPowerServerEnum.CRM_SERVER.name())) {
            // 查看该用户可以查看的权限字段，从表中查出
            List<String> fieldDataPowers = dataPowerService.getFieldDataPower(userId, orgId, tableName);
            logger.info("DataPowerAspect 不可查看字段fieldDataPowers =>>> {}", fieldDataPowers);
            // 如果不可看的字段为空，则该用户可以看该表下的所有字段。
            if (CollectionUtils.isEmpty(fieldDataPowers)) {
                return proceed;
            }
            // 去除集合中的null元素
            fieldDataPowers.removeAll(Collections.singleton(null));

            // 获取 接口返回数据对象 的data属性
            Field dataField = proceedClass.getDeclaredField("data");
            dataField.setAccessible(true);
            Object o = dataField.get(proceed);
            String result = JSON.toJSONString(o);
            logger.info("Member Detail/List toJSONString ==>{}", result);
            if (methodTypeName.equals(ApiDataPowerMethodEnum.LIST.name())) {
                // 序列化成对象类型，便于set数据为"-"
                MemberInfoDataApi memberInfoDataApi = JSON.parseObject(result, MemberInfoDataApi.class);
                logger.info("Member List memberInfoDataApi反序列化JSON对象 -> {}", memberInfoDataApi);

                if (memberInfoDataApi.getCount() == 0) {
                    return proceed;
                }
                List<MemberInfoDataApi.MemberInfo> memberInfos = memberInfoDataApi.getList().parallelStream()
                        .map(memberInfo -> {
                            for (String dataPower : fieldDataPowers) {
                                for (String tempDataPower : dataPower.split(",")) {
                                    try {
                                        Field field = memberInfo.getClass().getDeclaredField(tempDataPower);
                                        field.setAccessible(true);
                                        String fieldType = field.getType().getSimpleName();
                                        if ("Integer".equals(fieldType)) {
                                            field.set(memberInfo, null);
                                        } else {
                                            field.set(memberInfo, "****");
                                        }
                                    } catch (NoSuchFieldException e) {
                                        logger.warn("DataPowerAspect =>>> Some filed in table , but not in ResponseBody Data");
                                    } catch (Exception e) {
                                        logger.warn("DataPowerAspect =>>> field data power set field error");
                                    }
                                }
                            }
                            return memberInfo;
                        }).collect(Collectors.toList());
                memberInfoDataApi.setList(memberInfos);
                // 设置修改后的属性值给data属性
                dataField.set(proceed, memberInfoDataApi);
                logger.info("DataPowerAspect return data ---> {}", JSON.toJSONString(dataField.get(proceed)));
                return proceed;
            } else if (methodTypeName.equals(ApiDataPowerMethodEnum.DETAIL.name())) {
                MemberDetailDataApi memberDetailDataApi = JSON.parseObject(result, MemberDetailDataApi.class);
                logger.info("会员详情memberDetailDataApi反序列化JSON对象 -> {}", memberDetailDataApi);
                for (String dataPower : fieldDataPowers) {
                    for (String tempDatePower : dataPower.split(",")) {
                        try {
                            Field field = memberDetailDataApi.getClass().getDeclaredField(tempDatePower);
                            field.setAccessible(true);
                            String fieldType = field.getType().getSimpleName();
                            if ("List".equals(fieldType)) {
                                List<String> listFlag = new ArrayList<>();
                                listFlag.add("****");
                                field.set(memberDetailDataApi, listFlag);
                            } else {
                                field.set(memberDetailDataApi, "****");
                            }
                        } catch (NoSuchFieldException e) {
                            logger.warn("java.lang.NoSuchFieldException -> {}", tempDatePower);
                        } catch (SecurityException e) {
                            logger.warn("java.lang.SecurityException -> {}", tempDatePower);
                        } catch (IllegalArgumentException e) {
                            logger.warn("java.lang.IllegalArgumentException -> {}", tempDatePower);
                        }
                    }
                }
                logger.info("会员详情数据过滤结果 -> {}", memberDetailDataApi);
                // 设置修改后的属性值给data属性
                dataField.set(proceed, memberDetailDataApi);
                return proceed;
            }
        }
        return proceed;
    }
}